//Mprpc的日志系统，设计成单例模式
//在框架或者说软件运行的过程中会出现很多的正常的输出信息和错误信息，我们不可能将它全部打印在显示器上，
//运行时间长了，屏幕上输出的信息特别多，万一有什么问题我们也不好定位，出了问题一般看日志。
//当rpc请求过来的时候，在运行的时候就会产生信息，这时候需要写日志信息，但是写日志信息本质上是一个磁盘i/o，
//它是很慢的，如果要把写日志信息这一部分的开销也算在rpc业务请求执行的这个过程中，这样rpc执行请求业务的处理效率实在是太慢了，
#pragma once
#include"lockqueue.h"
#include<string>

enum LogLevel
{
    INFO,//普通信息
    ERROR,//错误信息
};


class Logger
{
public:
    static Logger& GetInstance();
    void SetLogLevel(LogLevel);//设置日志的级别
    void Log(std::string msg);//设置日志的信息
private:
   
   int m_loglevel;//日志的级别
   LockQueue<std::string> m_lockQueue;//日志缓冲队列

   Logger();
   Logger(const Logger&)=delete;
   Logger(Logger&&)=delete;

};

//在用户使用日志的时候，不需要让用户自己去获取Logger的实例，自己用实例去写日志，所以我们可以定义宏,以可变参数的方式为用户提供更方便更快捷的日志写入方式
//支持可变参数，用户在写日志的时候可以使用自己的风格 
//使用:: LOG_INFO("xxx %d %s",2000,"xxx")
#define LOG_INFO(logmsgformat, ...) \
do \
{  \
    Logger& logger=Logger::GetInstance(); \
    logger.SetLogLevel(INFO); \
    char c[1024]={0}; \
    snprintf(c,1024,logmsgformat, ##__VA_ARGS__); \
    logger.Log(c);\
}while(0);

#define LOG_ERR(logmsgformat, ...) \
do \
{  \
    Logger& logger=Logger::GetInstance(); \
    logger.SetLogLevel(ERROR); \
    char c[1024]={0}; \
    snprintf(c,1024,logmsgformat, ##__VA_ARGS__); \
    logger.Log(c);\
}while(0);
